#pragma once

#include <memory>
#include <functional>

#include "Socket.hpp"
#include "Log.hpp"
using service_t = std::function<std::string(std::string &)>;
class TCPServer
{
public:
    TCPServer(service_t service, uint16_t port = gport)
        : _service(service),
          _port(port)
    {
        _listensock = std::make_shared<tcp_Socket>();
        _listensock->BuildListenSocket();
    }

    class Threaddata
    {
    public:
        Threaddata(SockPtr sockptr, TCPServer *self, InetAddr client)
            : _self(self), _client(client), _sockptr(sockptr)
        {
        }

    public:
        SockPtr _sockptr;
        TCPServer *_self;
        InetAddr _client;
    };
    void Loop()
    {
        _isrunning = true;
        while (true)
        {
            // 连接过程中产生新的用户端结构体和套接字指针
            InetAddr client;
            SockPtr newsock = _listensock->Accepter(&client);
            if (newsock == nullptr)
                continue;
            LOG(INFO, "get a new link, client info : %s, sockfd is : %d\n", client.AddrString().c_str(), newsock->Sockfd());
            // version 2 ---- 多线程版本 --- 不能关闭fd了，也不需要了
            pthread_t tid;
            Threaddata *td = new Threaddata(newsock, this, client);
            pthread_create(&tid, nullptr, Excute, td);
        }
        _isrunning = false;
    }
    static void *Excute(void *args)
    {
        pthread_detach(pthread_self());
        Threaddata *td = static_cast<Threaddata *>(args);
        // 调用该对象的的service服务
        // 因为是static函数，需通过this调用

        std::string requeststr;
        ssize_t n = td->_sockptr->Recv(&requeststr);
        // 正文部分直接被截掉了

        if (n > 0)
        {
            if (n == 666)
            {
                std::cout << "继续读取" << std::endl;
                n = td->_sockptr->Recv(&requeststr);
            }
            else if(n == 693)
            {
                std::cout << "读取完整" << std::endl;
            }
            std::string responsestr = td->_self->_service(requeststr);
            td->_sockptr->Send(responsestr);
        }
        td->_sockptr->Close();
        delete td;
        return nullptr;
    }

private:
    bool _isrunning;
    SockPtr _listensock;
    uint16_t _port;
    service_t _service;
};